home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
prog_gen
/
freeli10.zip
/
FREELIB2.ASX
< prev
next >
Wrap
Text File
|
1996-04-20
|
61KB
|
2,223 lines
~~~C_STR1
Ideal
Public strlen,strcpy,strcat,strcmp
Model Tiny
CodeSeg
P186
;****************** strlen() -- Get length of string
;int strlen(char *strp);
strp equ bp+4
Proc strlen
push bp ;Set up stack frame
mov bp,sp
push si ;Save SI
mov si,[strp] ;SI = string pointer
p1_loop: lodsb ;Load char
test al,al ;Loop while not zero
jnz p1_loop
sub si,[strp] ;AX = length
dec si
mov ax,si
pop si ;Restore SI
pop bp ;Delete stack frame
ret 2 ;Return
EndP strlen
;****************** strcpy() -- Copy a string
;void strcpy(char *str1, char *str2);
str1 equ bp+6
str2 equ bp+4
Proc strcpy
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov si,[str2] ;SI = source
mov di,[str1] ;DI = destination
p2_loop: lodsb ;Load char
mov [di],al ;Store char
inc di
test al,al ;Loop while not zero
jnz p2_loop
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP strcpy
;****************** strcat() -- Concatenate strings
;void strcat(char *str1, char *str2);
str1 equ bp+6
str2 equ bp+4
Proc strcat
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov si,[str1] ;SI = destination
p3_cloop: lodsb ;Load char
test al,al ;Loop while not zero
jnz p3_cloop
mov di,si ;DI = destination
mov si,[str2] ;SI = source
dec di
p3_loop: lodsb ;Load char
mov [di],al ;Store char
inc di
test al,al ;Loop while not zero
jnz p3_loop
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP strcat
;****************** strcmp() -- Compare strings
;void strcmp(char *str1, char *str2);
str1 equ bp+6
str2 equ bp+4
Proc strcmp
push bp ;Set up stack frame
mov bp,sp
push si di ;Save registers
mov si,[str1] ;SI = source
mov di,[str2] ;DI = destination
p4_loop: lodsb ;Load char 1
mov ah,[di] ;Load char 2
inc di
cmp al,ah ;Not equal?
jne p4_nope
test al,al ;Loop while not zero
jnz p4_loop
xor ax,ax ;Equal, return 0
p4_done: pop di si ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p4_nope: sub al,ah ;Not equal, return difference
mov ah,0 ;in first unequal position
sbb ah,0
jmp p4_done
EndP strcmp
End
~~~C_STR2
Ideal
Extrn strlen:near
Public strchr,strstr
Model Tiny
CodeSeg
P186
;****************** strchr() -- Search string for char
;int strchr(char *strp, int chr);
strp equ bp+6
chr equ bp+4
Proc strchr
push bp ;Set up stack frame
mov bp,sp
push si ;Save SI
mov si,[strp] ;SI = string pointer
mov ah,[chr] ;AH = char
p1_loop: lodsb ;Load char
test al,al ;Null, not found
jz p1_nope
cmp al,ah ;Loop while not equal
jne p1_loop
sub si,[strp] ;AX = position of char
dec si
mov ax,si
p1_done: pop si ;Restore SI
pop bp ;Delete stack frame
ret 4 ;Return
p1_nope: mov ax,-1 ;Not found, return -1
jmp p1_done
EndP strchr
;****************** strstr() -- Search string for substring
;int strstr(char *strp, char *subp);
strp equ bp+6
subp equ bp+4
Proc strstr
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
pusha
push ds ;ES = DS
pop es
mov si,[strp] ;SI = string pointer
mov bx,[subp] ;BX = substring pointer
push bx ;Get length of substring
call strlen ;into DX
mov dx,ax
mov ah,[bx] ;AH = first char
p3_loop: lodsb ;Load char
test al,al ;Null, not found
jz p3_nope
cmp al,ah ;Loop while not equal
jne p3_loop
mov cx,dx ;CX = length
mov di,bx ;DI = substring
push si ;Save SI
dec si ;Push back char
repe cmpsb ;Compare strings
pop si ;Restore SI
jne p3_loop ;Loop if not equal
sub si,[strp] ;AX = position of char
dec si
mov es,si ;Sneaky: save it in ES
p3_done: popa ;Restore registers
mov ax,es ;Return value in AX
pop es
pop bp ;Delete stack frame
ret 4 ;Return
p3_nope: mov ax,-1 ;Not found, return -1
mov es,ax
jmp p3_done
EndP strstr
End
~~~C_STR3
Ideal
Public stricmp,strlwr,strupr
Model Tiny
CodeSeg
P186
;****************** stricmp() -- Compare strings, case insensitive
;void stricmp(char *str1, char *str2);
str1 equ bp+6
str2 equ bp+4
Proc stricmp
push bp ;Set up stack frame
mov bp,sp
push si di ;Save registers
mov si,[str1] ;SI = source
mov di,[str2] ;DI = destination
p1_loop: lodsb ;Load char 1
mov ah,[di] ;Load char 2
inc di
cmp al,'a' ;Convert AL to uppercase
jb p1_setAH
cmp al,'z'
ja p1_setAH
sub al,20h
p1_setAH: cmp ah,'a' ;Convert AH to uppercase
jb p1_comp
cmp ah,'z'
ja p1_comp
sub ah,20h
p1_comp: cmp al,ah ;Equal?
jne p1_nope
test al,al ;Loop while not zero
jnz p1_loop
inc ax ;Equal, return 1
p1_done: pop di si ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_nope: xor ax,ax ;Not equal, return 0
jmp p1_done
EndP stricmp
;****************** strlwr() -- Convert string to lowercase
;int strlwr(char *strp);
strp equ bp+4
Proc strlwr
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
mov si,[strp] ;SI = string pointer
p2_loop: lodsb ;Load char
test al,al ;Check for null
jz p2_done
cmp al,'A' ;Check for uppercase
jb p2_loop
cmp al,'Z'
ja p2_loop
add al,20h ;Convert to lowercase
mov [si-1],al ;Store char
jmp p2_loop
p2_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP strlwr
;****************** strupr() -- Convert string to uppercase
;int strupr(char *strp);
strp equ bp+4
Proc strupr
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
mov si,[strp] ;SI = string pointer
p3_loop: lodsb ;Load char
test al,al ;Check for null
jz p3_done
cmp al,'a' ;Check for lowercase
jb p3_loop
cmp al,'z'
ja p3_loop
sub al,20h ;Convert to uppercase
mov [si-1],al ;Store char
jmp p3_loop
p3_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP strupr
End
~~~C_STR4
Ideal
Public strrtrim,strltrim
Model Tiny
CodeSeg
P186
;****************** strrtrim() -- Trim trailing spaces off a string
;int strrtrim(char *strp);
strp equ bp+4
Proc strrtrim
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
mov si,[strp] ;SI = string pointer
mov di,si ;DI = SI
p1_loop: lodsb ;Load char
test al,al ;Check for null
jz p1_done
cmp al,' ' ;Check for space
je p1_loop
mov di,si ;Set pointer
jmp p1_loop
p1_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP strrtrim
;****************** strltrim() -- Trim leading spaces off a string
;int strltrim(char *strp);
strp equ bp+4
Proc strltrim
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
mov si,[strp] ;SI, DI = string pointer
mov di,si
p2_loop: lodsb ;Load char
test al,al ;Check for null
jz p2_cont
cmp al,' ' ;Loop while space
je p2_loop
p2_cont: dec si ;Move back one char
cmp si,di ;No spaces, quit
je p2_done
p2_cloop: lodsb ;Shift the string over
mov [di],al
inc di
test al,al
jnz p2_cloop
p2_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP strltrim
End
~~~C_MEM1
Ideal
Public memcpy,memset
Model Tiny
CodeSeg
P186
;****************** memcpy() -- Copy memory block
;void memcpy(void *p1, void *p2, int nbytes);
p1 equ bp+8
p2 equ bp+6
nbytes equ bp+4
Proc memcpy
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
pusha
push ds ;ES = DS
pop es
mov si,[p2] ;SI = source
mov di,[p1] ;DI = destination
mov cx,[nbytes] ;CX = count
cmp di,si ;Make forward moves
jb p1_go ;in reverse
je p1_done
std ;Set direction flag
add si,cx ;Move offsets to end
add di,cx
dec si
dec di
p1_go: rep movsb ;Copy memory
p1_done: cld ;Clear direction flag
popa ;Restore registers
pop es
pop bp ;Delete stack frame
ret 6 ;Return
EndP memcpy
;****************** memset() -- Set memory block
;void memset(void *ptr, int nbytes, int chr);
ptr equ bp+8
nbytes equ bp+6
chr equ bp+4
Proc memset
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
pusha
push ds ;ES = DS
pop es
mov di,[ptr] ;DI = block
mov cx,[nbytes] ;CX = count
mov al,[chr] ;AL = char
rep stosb ;Set memory
popa ;Restore registers
pop es
pop bp ;Delete stack frame
ret 6 ;Return
EndP memset
End
~~~C_MEM2
Ideal
Public memcmp,memchr
Model Tiny
CodeSeg
P186
;****************** memcmp() -- Compare memory blocks
;void memcmp(void *p1, void *p2, int nbytes);
p1 equ bp+8
p2 equ bp+6
nbytes equ bp+4
Proc memcmp
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
push cx si di
push ds ;ES = DS
pop es
mov si,[p2] ;SI = source
mov di,[p1] ;DI = destination
mov cx,[nbytes] ;CX = count
repe cmpsb ;Compare memory
mov ax,1 ;Assume equal
je p1_done ;Jump if equal
xor ax,ax ;Not equal, return 0
p1_done: pop di si cx ;Restore registers
pop es
pop bp ;Delete stack frame
ret 6 ;Return
EndP memcmp
;****************** memchr() -- Scan memory for char
;void memchr(void *ptr, int nbytes, int chr);
ptr equ bp+8
nbytes equ bp+6
chr equ bp+4
Proc memchr
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
push cx si di
push ds ;ES = DS
pop es
mov di,[ptr] ;DI = block
mov cx,[nbytes] ;CX = count
mov al,[chr] ;AL = char
repne scasb ;Scan memory
jne p2_nope ;Jump if not found
sub di,[ptr] ;AX = position of char
dec di
mov ax,di
p2_done: pop di si cx ;Restore registers
pop es
pop bp ;Delete stack frame
ret 6 ;Return
p2_nope: mov ax,-1 ;Not found, return -1
jmp p2_done
EndP memchr
End
~~~C_ISRCH
Ideal
Public isearch
Model Tiny
P186
CodeSeg
;****************** isearch() -- Search a sorted array of integers
;int isearch(int *ary, int size, int elem);
ary equ bp+8
size equ bp+6
elem equ bp+4
Proc isearch
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si di ;Save registers
mov bx,[ary] ;BX = array
xor cx,cx ;CX = lower limit
mov dx,[size] ;DX = upper limit
dec dx
p1_loop: mov si,cx ;SI = middle element
add si,dx
shr si,1
add si,si
mov ax,[bx+si] ;Get element
shr si,1 ;Fix SI
cmp ax,[elem] ;Check element
je p1_found ;Equal?
jl p1_less ;Too low?
p1_greater: mov di,si ;Set first half
mov si,cx
jmp p1_cont
p1_less: mov di,dx ;Set second half
inc si
p1_cont: cmp cx,dx ;Min = Max, done
je p1_nope
mov cx,si ;Set limits
mov dx,di
jmp p1_loop ;Loop back
p1_found: mov ax,si ;AX = result
p1_done: pop di si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 6 ;Return
p1_nope: mov ax,-1 ;Not found, return -1
jmp p1_done
EndP isearch
End
~~~C_LSRCH
Ideal
Public lsearch
Model Tiny
P186
CodeSeg
;****************** lsearch() -- Search a sorted array of longs
;int lsearch(long *ary, int size, long elem);
ary equ bp+10
size equ bp+8
elem equ bp+4
Proc lsearch
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si di ;Save registers
mov bx,[ary] ;BX = array
xor cx,cx ;CX = lower limit
mov dx,[size] ;DX = upper limit
dec dx
p2_loop: mov si,cx ;SI = middle element
add si,dx
shr si,1
shl si,2
mov ax,[bx+si] ;Get element
mov di,[bx+si+2]
shr si,2 ;Fix SI
cmp di,[elem+2] ;Check high word
jl p2_less ;Too low?
jg p2_greater ;Too high?
cmp ax,[elem] ;Check low word
je p2_found ;Equal?
jl p2_less ;Too low?
p2_greater: mov di,si ;Set first half
mov si,cx
dec di
jmp p2_cont
p2_less: mov di,dx ;Set second half
inc si
p2_cont: cmp cx,dx ;Min = Max, done
je p2_nope
mov cx,si ;Set limits
mov dx,di
jmp p2_loop ;Loop back
p2_found: mov ax,si ;AX = result
p2_done: pop di si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
p2_nope: mov ax,-1 ;Not found, return -1
jmp p2_done
EndP lsearch
End
~~~C_XSRCH
Ideal
Public xsearch
Model Tiny
P186
CodeSeg
;****************** xsearch() -- Search sorted array, generalized
;int xsearch(void **ary, int size, void *elem, void *func);
ary equ bp+10
size equ bp+8
elem equ bp+6
func equ bp+4
Proc xsearch
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si di ;Save registers
mov bx,[ary] ;BX = array
xor cx,cx ;CX = lower limit
mov dx,[size] ;DX = upper limit
dec dx
p3_loop: mov si,cx ;SI = middle element
add si,dx
shr si,1
add si,si
mov ax,[bx+si] ;Get element
shr si,1 ;Fix SI
push ax [elem] ;Check element
call [word func]
test ax,ax
je p3_found ;Equal?
jl p3_less ;Too low?
p3_greater: mov di,si ;Set first half
mov si,cx
jmp p3_cont
p3_less: mov di,dx ;Set second half
inc si
p3_cont: cmp cx,dx ;Min = Max, done
je p3_nope
mov cx,si ;Set limits
mov dx,di
jmp p3_loop ;Loop back
p3_found: mov ax,si ;AX = result
p3_done: pop di si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
p3_nope: mov ax,-1 ;Not found, return -1
jmp p3_done
EndP xsearch
End
~~~C_SSRCH
Ideal
Extrn strcmp:near
Public ssearch
Model Tiny
P186
CodeSeg
;****************** ssearch() -- Search a sorted array of strings
;int ssearch(char **ary, int size, char *elem);
ary equ bp+8
size equ bp+6
elem equ bp+4
Proc ssearch
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si di ;Save registers
mov bx,[ary] ;BX = array
xor cx,cx ;CX = lower limit
mov dx,[size] ;DX = upper limit
dec dx
p1_loop: mov si,cx ;SI = middle element
add si,dx
shr si,1
add si,si
mov ax,[bx+si] ;Get element
shr si,1 ;Fix SI
push ax [elem] ;Check element
call strcmp
test ax,ax
je p1_found ;Equal?
jl p1_less ;Too low?
p1_greater: mov di,si ;Set first half
mov si,cx
jmp p1_cont
p1_less: mov di,dx ;Set second half
inc si
p1_cont: cmp cx,dx ;Min = Max, done
je p1_nope
mov cx,si ;Set limits
mov dx,di
dec di
jmp p1_loop ;Loop back
p1_found: mov ax,si ;AX = result
p1_done: pop di si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 6 ;Return
p1_nope: mov ax,-1 ;Not found, return -1
jmp p1_done
EndP ssearch
End
~~~C_ISORT
Ideal
Public isort
Model Tiny
P186
CodeSeg
;****************** isort() -- Sort an array of integers
;void isort(int *ary, int size);
ary equ bp+6
max equ bp+4
Proc isort
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov bx,[ary] ;Call recursive routine
xor cx,cx
mov dx,[max]
dec dx
add dx,dx
call p1_qsort
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_qsort: cmp cx,dx ;One element, return
je p1_ret
pusha
mov ax,dx ;Two elements, sort them
sub ax,cx
cmp ax,2
jne p1_cont
mov si,cx ;SI, DI = low, high
mov di,dx
mov ax,[bx+si] ;Check them
cmp ax,[bx+di]
jle p1_done
xchg ax,[bx+di] ;Switch them
mov [bx+si],ax
jmp p1_done
p1_cont: mov si,cx ;AX = middle element
add si,dx
shr si,2
add si,si
mov ax,[bx+si]
mov si,cx ;SI = low, DI = high
mov di,dx
p1_loop: cmp si,dx ;While [BX+SI] < AX and
jge p1_loop2 ; SI < DX, advance SI
cmp ax,[bx+si]
jle p1_loop2
add si,2
jmp p1_loop
p1_loop2: cmp di,cx ;While [BX+DI] > AX and
jle p1_cont2 ; DI > CX, advance DI
cmp ax,[bx+di]
jge p1_cont2
sub di,2
jmp p1_loop2
p1_cont2: cmp si,di ;Hit in middle, recurse
jge p1_rec
push [bx+si] ;Swap elements
push [bx+di]
pop [bx+si]
pop [bx+di]
add si,2 ;Advance SI, DI
sub di,2
jmp p1_loop ;Loop back
p1_rec: cmp cx,si ;If first half isn't empty,
je p1_skip1 ;recurse to sort it
xchg dx,di
call p1_qsort
xchg dx,di
p1_skip1: cmp dx,di ;If second half isn't empty,
je p1_done ;recurse to sort it
xchg cx,si
call p1_qsort
xchg cx,si
p1_done: popa ;Restore registers
p1_ret: ret ;Return
EndP isort
End
~~~C_LSORT
Ideal
Public lsort
Model Tiny
P186
CodeSeg
;****************** lsort() -- Sort an array of longs
;void lsort(long *ary, int size);
ary equ bp+6
max equ bp+4
num equ bp-4
Proc lsort
enter 4,0 ;Set up stack frame
pusha ;Save all registers
mov bx,[ary] ;Call recursive routine
xor cx,cx
mov dx,[max]
dec dx
shl dx,2
call p1_qsort
popa ;Restore registers
leave ;Delete stack frame
ret 4 ;Return
p1_done: popa ;Restore registers
p1_ret: ret ;Return
p1_qsort: cmp cx,dx ;One element, return
je p1_ret
pusha
mov ax,dx ;Two elements, sort them
sub ax,cx
cmp ax,4
jne p1_cont
mov si,cx ;SI, DI = low, high
mov di,dx
mov dx,[bx+si+2] ;Check them
mov ax,[bx+si]
cmp dx,[bx+di+2]
jl p1_done
jg p1_swap2
cmp ax,[bx+di]
jle p1_done
p1_swap2: xchg ax,[bx+di] ;Switch them
mov [bx+si],ax
xchg dx,[bx+di+2]
mov [bx+si+2],dx
jmp p1_done
p1_cont: mov si,cx ;NUM = middle element
add si,dx
shr si,3
shl si,2
mov ax,[bx+si]
mov [num],ax
mov ax,[bx+si+2]
mov [num+2],ax
mov si,cx ;SI = low, DI = high
mov di,dx
p1_loop: cmp si,dx ;While [BX+SI] < NUM and
jge p1_loop2 ; SI < DX, advance SI
mov ax,[num+2]
cmp ax,[bx+si+2]
jl p1_loop2
jg p1_go1
mov ax,[num]
cmp ax,[bx+si]
jle p1_loop2
p1_go1: add si,4
jmp p1_loop
p1_loop2: cmp di,cx ;While [BX+DI] > NUM and
jle p1_cont2 ; DI > CX, advance DI
mov ax,[num+2]
cmp ax,[bx+di+2]
jg p1_cont2
jl p1_go2
mov ax,[num]
cmp ax,[bx+di]
jge p1_cont2
p1_go2: sub di,4
jmp p1_loop2
p1_cont2: cmp si,di ;Hit in middle, recurse
jge p1_rec
push [bx+si] ;Swap elements
push [bx+di]
pop [bx+si]
pop [bx+di]
push [bx+si+2]
push [bx+di+2]
pop [bx+si+2]
pop [bx+di+2]
add si,4 ;Advance SI, DI
sub di,4
jmp p1_loop ;Loop back
p1_rec: cmp cx,si ;If first half isn't empty,
je p1_skip1 ;recurse to sort it
xchg dx,di
call p1_qsort
xchg dx,di
p1_skip1: cmp dx,di ;If second half isn't empty,
je p1_done2 ;recurse to sort it
xchg cx,si
call p1_qsort
xchg cx,si
p1_done2: jmp p1_done ;Return
EndP lsort
End
~~~C_SSORT
Ideal
Extrn strcmp:near
Public ssort
Model Tiny
P186
CodeSeg
;****************** ssort() -- Sort an array of strings
;void ssort(char **ary, int size);
ary equ bp+6
max equ bp+4
Proc ssort
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov bx,[ary] ;Call recursive routine
xor cx,cx
mov dx,[max]
dec dx
add dx,dx
call p1_qsort
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_qsort: cmp cx,dx ;One element, return
jne $+3
ret
pusha
mov ax,dx ;Two elements, sort them
sub ax,cx
cmp ax,2
jne p1_cont
mov si,cx ;SI, DI = low, high
mov di,dx
mov ax,[bx+si] ;Check them
push ax [bx+di]
call strcmp
test ax,ax
jle p1_done
push [bx+si] ;Switch them
push [bx+di]
pop [bx+si]
pop [bx+di]
jmp p1_done
p1_cont: mov si,cx ;AX = middle element
add si,dx
shr si,2
add si,si
mov ax,[bx+si]
mov si,cx ;SI = low, DI = high
mov di,dx
p1_loop: cmp si,dx ;While [BX+SI] < AX and
jge p1_loop2 ; SI < DX, advance SI
push ax ax [bx+si]
call strcmp
pop ax
jle p1_loop2
add si,2
jmp p1_loop
p1_loop2: cmp di,cx ;While [BX+DI] > AX and
jle p1_cont2 ; DI > CX, advance DI
push ax ax [bx+di]
call strcmp
pop ax
jge p1_cont2
sub di,2
jmp p1_loop2
p1_cont2: cmp si,di ;Hit in middle, recurse
jge p1_rec
push [bx+si] ;Swap elements
push [bx+di]
pop [bx+si]
pop [bx+di]
add si,2 ;Advance SI, DI
sub di,2
jmp p1_loop ;Loop back
p1_rec: cmp cx,si ;If first half isn't empty,
je p1_skip1 ;recurse to sort it
xchg dx,di
call p1_qsort
xchg dx,di
p1_skip1: cmp dx,di ;If second half isn't empty,
je p1_done ;recurse to sort it
xchg cx,si
call p1_qsort
xchg cx,si
p1_done: popa ;Restore registers
p1_ret: ret ;Return
EndP ssort
End
~~~C_XSORT
Ideal
Public xsort
Model Tiny
P186
CodeSeg
;****************** xsort() -- Sort array, generalized
;void xsort(void **ary, int size, void *func);
ary equ bp+8
max equ bp+6
func equ bp+4
Proc xsort
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov bx,[ary] ;Call recursive routine
xor cx,cx
mov dx,[max]
dec dx
add dx,dx
call p1_qsort
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_qsort: cmp cx,dx ;One element, return
jne $+3
ret
pusha
mov ax,dx ;Two elements, sort them
sub ax,cx
cmp ax,2
jne p1_cont
mov si,cx ;SI, DI = low, high
mov di,dx
mov ax,[bx+si] ;Check them
push ax [bx+di]
call [word func]
test ax,ax
jle p1_done
push [bx+si] ;Switch them
push [bx+di]
pop [bx+si]
pop [bx+di]
jmp p1_done
p1_cont: mov si,cx ;AX = middle element
add si,dx
shr si,2
add si,si
mov ax,[bx+si]
mov si,cx ;SI = low, DI = high
mov di,dx
p1_loop: cmp si,dx ;While [BX+SI] < AX and
jge p1_loop2 ; SI < DX, advance SI
push ax ax [bx+si]
call [word func]
pop ax
jle p1_loop2
add si,2
jmp p1_loop
p1_loop2: cmp di,cx ;While [BX+DI] > AX and
jle p1_cont2 ; DI > CX, advance DI
push ax ax [bx+di]
call [word func]
pop ax
jge p1_cont2
sub di,2
jmp p1_loop2
p1_cont2: cmp si,di ;Hit in middle, recurse
jge p1_rec
push [bx+si] ;Swap elements
push [bx+di]
pop [bx+si]
pop [bx+di]
add si,2 ;Advance SI, DI
sub di,2
jmp p1_loop ;Loop back
p1_rec: cmp cx,si ;If first half isn't empty,
je p1_skip1 ;recurse to sort it
xchg dx,di
call p1_qsort
xchg dx,di
p1_skip1: cmp dx,di ;If second half isn't empty,
je p1_done ;recurse to sort it
xchg cx,si
call p1_qsort
xchg cx,si
p1_done: popa ;Restore registers
p1_ret: ret ;Return
EndP xsort
End
~~~C_LSHL
Ideal
Public lshl
Model Tiny
CodeSeg
P186
;****************** lshl() -- Shift long integer to the left
;long lshl(long x, int d); 37 clocks (486)
x equ bp+6
d equ bp+4
Proc lshl
push bp ;Set up stack frame
mov bp,sp
push cx ;Save CX
mov ax,[x] ;DX:AX = x
mov dx,[x+2]
mov cl,[d] ;CL = distance
cmp cl,16 ;Distance > 16?
jb p1_cont ;Jump if not
mov dx,ax ;Shift left 16
xor ax,ax
p1_cont: and cl,15 ;Mask off high part
push ax cx ;Save AX, CX
shl dx,cl ;DX = (DX shl CL) +
xor cl,15 ; (AX shr (16 - CL))
inc cx
shr ax,cl
add dx,ax
pop cx ax ;Restore AX, CX
shl ax,cl ;AX = AX shl CL
pop cx ;Restore CX
pop bp ;Delete stack frame
ret 6 ;Return
EndP lshl
End
~~~C_LSHR
Ideal
Public lshr
Model Tiny
CodeSeg
P186
;****************** lshr() -- Shift long integer to the right
;long lshr(long x, int d); 37 clocks (486)
x equ bp+6
d equ bp+4
Proc lshr
push bp ;Set up stack frame
mov bp,sp
push cx ;Save CX
mov ax,[x] ;DX:AX = x
mov dx,[x+2]
mov cl,[d] ;CL = distance
cmp cl,16 ;Distance > 16?
jb p1_cont ;Jump if not
mov ax,dx ;Shift right 16
xor dx,dx
p1_cont: and cl,15 ;Mask off high part
push dx cx ;Save DX, CX
shr ax,cl ;AX = (AX shr CL) +
xor cl,15 ; (DX shl (16 - CL))
inc cx
shl dx,cl
add ax,dx
pop cx dx ;Restore DX, CX
shr dx,cl ;DX = DX shr CL
pop cx ;Restore CX
pop bp ;Delete stack frame
ret 6 ;Return
EndP lshr
End
~~~C_LSAR
Ideal
Public lsar
Model Tiny
CodeSeg
P186
;****************** lsar() -- Shift long integer to the right, signed
;long lsar(long x, int d); 39 clocks (486)
x equ bp+6
d equ bp+4
Proc lsar
push bp ;Set up stack frame
mov bp,sp
push cx ;Save CX
mov ax,[x] ;DX:AX = x
mov dx,[x+2]
mov cl,[d] ;CL = distance
cmp cl,16 ;Distance > 16?
jb p1_cont ;Jump if not
mov ax,dx ;Shift right 16
cbw
p1_cont: and cl,15 ;Mask off high part
push dx cx ;Save DX, CX
shr ax,cl ;AX = (AX shr CL) +
xor cl,15 ; (DX shl (16 - CL))
inc cx
shl dx,cl
add ax,dx
pop cx dx ;Restore DX, CX
sar dx,cl ;DX = DX sar CL
pop cx ;Restore CX
pop bp ;Delete stack frame
ret 6 ;Return
EndP lsar
End
~~~C_LMUL
Ideal
Public lmul
Model Tiny
CodeSeg
P186
;****************** lmul() -- Multiply long integers
;long lmul(long x, long y); 70 clocks (486)
x equ bp+8
y equ bp+4
Proc lmul
push bp ;Set up stack frame
mov bp,sp
push bx ;Save registers
mov ax,[x] ;Multiply low words
mul [word y]
mov bx,dx ;BX = high word
push ax ;Save low word
mov ax,[x+2] ;Multiply high by low Y
mul [word y]
add bx,ax ;Add in result
mov ax,[y+2] ;Multiply high by low X
mul [word x]
add ax,bx ;Add in result
pop dx ;Restore low word
xchg dx,ax ;DX:AX = result
pop bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP lmul
End
~~~C_LIMUL
Ideal
Public limul
Model Tiny
CodeSeg
P186
;****************** limul() -- Multiply long integers, signed
;long limul(long x, long y); 89-97 clocks (486)
x equ bp+8
y equ bp+4
Proc limul
push bp ;Set up stack frame
mov bp,sp
push bx cx ;Save registers
xor cx,cx ;Clear neg flag
mov ax,[x+2] ;AX = x high word
test ax,ax ;Negative?
jge p1_xok
neg ax ;Negate X
neg [word x]
sbb ax,0
not cx ;Set neg flag
p1_xok: mov [x+2],ax ;Save X
mov ax,[y+2] ;AX = y high word
test ax,ax ;Negative?
jge p1_yok
neg ax ;Negate Y
neg [word y]
sbb ax,0
not cx ;Flip neg flag
p1_yok: mov [y+2],ax ;Save Y
mov ax,[x] ;Multiply low words
mul [word y]
mov bx,dx ;BX = high word
push ax ;Save low word
mov ax,[x+2] ;Multiply high by low Y
mul [word y]
add bx,ax ;Add in result
mov ax,[y+2] ;Multiply high by low X
mul [word x]
add ax,bx ;Add in result
pop dx ;Restore low word
xchg dx,ax ;DX:AX = result
test cx,cx ;Check neg flag
jz p1_done
neg dx ;Negate result
neg ax
sbb dx,0
p1_done: pop cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP limul
End
~~~C_LDIV
Ideal
Public ldiv
Model Tiny
CodeSeg
P186
;****************** ldiv() -- Divide long integers
;long ldiv(long x, long y); 692-948 clocks (486)
x equ bp+8
y equ bp+4
Proc ldiv
push bp ;Set up stack frame
mov bp,sp
push bx cx si ;Save registers
xor ax,ax ;Clear DX:AX, CX:BX
xor bx,bx ;DX:AX will contain
xor cx,cx ;the result, and
xor dx,dx ;CX:BX will be X.
mov si,32 ;SI = count
p1_loop: shl [word x],1 ;Shift in one bit of X
rcl [word x+2],1
adc bx,bx
adc cx,cx
add ax,ax ;Shift result left by 1
adc dx,dx
cmp cx,[y+2] ;Compare the partial X
jb p1_skip ;to Y, if X is bigger
ja p1_sub ;then Y is subtracted
cmp bx,[y] ;from the partial X.
jb p1_skip
p1_sub: sub bx,[y] ;Subtract Y from partial X
sbb cx,[y+2]
add ax,1 ;Add one bit to result
adc dx,0
p1_skip: dec si ;Loop back
jnz p1_loop
pop si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP ldiv
End
~~~C_LIDIV
Ideal
Public lidiv
Model Tiny
CodeSeg
P186
;****************** lidiv() -- Divide long integers, signed
;long lidiv(long x, long y); 711-975 clocks (486)
x equ bp+8
y equ bp+4
Proc lidiv
push bp ;Set up stack frame
mov bp,sp
push bx cx si ;Save registers
xor cx,cx ;Clear neg flag
mov ax,[x+2] ;AX = x high word
test ax,ax ;Negative?
jge p1_xok
neg ax ;Negate X
neg [word x]
sbb ax,0
not cx ;Set neg flag
p1_xok: mov [x+2],ax ;Save X
mov ax,[y+2] ;AX = y high word
test ax,ax ;Negative?
jge p1_yok
neg ax ;Negate Y
neg [word y]
sbb ax,0
not cx ;Flip neg flag
p1_yok: mov [y+2],ax ;Save Y
push cx ;Save neg flag
xor ax,ax ;Clear DX:AX, CX:BX
xor bx,bx ;DX:AX will contain
xor cx,cx ;the result, and
xor dx,dx ;CX:BX will be X.
mov si,32 ;SI = count
p1_loop: shl [word x],1 ;Shift in one bit of X
rcl [word x+2],1
adc bx,bx
adc cx,cx
add ax,ax ;Shift result left by 1
adc dx,dx
cmp cx,[y+2] ;Compare the partial X
jb p1_skip ;to Y, if X is bigger
ja p1_sub ;then Y is subtracted
cmp bx,[y] ;from the partial X.
jb p1_skip
p1_sub: sub bx,[y] ;Subtract Y from partial X
sbb cx,[y+2]
add ax,1 ;Add one bit to result
adc dx,0
p1_skip: dec si ;Loop back
jnz p1_loop
pop cx ;Restore neg flag
test cx,cx ;Check neg flag
jz p1_done
neg dx ;Negate result
neg ax
sbb dx,0
p1_done: pop si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP lidiv
End
~~~C_FIXMUL
Ideal
Public fixmul
Model Tiny
CodeSeg
P186
;****************** fixmul() -- Multiply fixed point numbers
;long fixmul(long x, long y); 101-109 clocks (486)
x equ bp+8
y equ bp+4
Proc fixmul
push bp ;Set up stack frame
mov bp,sp
push bx cx si ;Save registers
xor si,si ;Clear neg flag
mov ax,[x+2] ;AX = x high word
test ax,ax ;Negative?
jge p1_xok
neg ax ;Negate X
neg [word x]
sbb ax,0
not si ;Set neg flag
p1_xok: mov [x+2],ax ;Save X
mov ax,[y+2] ;AX = y high word
test ax,ax ;Negative?
jge p1_yok
neg ax ;Negate Y
neg [word y]
sbb ax,0
not si ;Flip neg flag
p1_yok: mov [y+2],ax ;Save Y
mov ax,[x+2] ;Multiply high by low Y
mul [word y]
mov cx,dx ;Save in CX:BX
mov bx,ax
mov ax,[y+2] ;Multiply high by low X
mul [word x]
add bx,ax ;Add in result
adc cx,dx
mov ax,[x] ;Multiply low words
mul [word y]
add bx,dx ;Add in result
adc cx,0
mov ax,[x+2] ;Multiply high words
mul [word y+2]
add ax,cx ;Add in result
mov dx,bx ;DX:AX = result
xchg dx,ax
test si,si ;Check neg flag
jz p1_done
neg dx ;Negate result
neg ax
sbb dx,0
p1_done: pop si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP fixmul
End
~~~C_FIXDIV
Ideal
Public fixdiv
Model Tiny
CodeSeg
P186
;****************** fixdiv() -- Divide fixed point numbers
;long fixdiv(long x, long y); 1028-1412 clocks (486)
x equ bp+8
y equ bp+4
Proc fixdiv
push bp ;Set up stack frame
mov bp,sp
push bx cx si ;Save registers
xor cx,cx ;Clear neg flag
mov ax,[x+2] ;AX = x high word
test ax,ax ;Negative?
jge p1_xok
neg ax ;Negate X
neg [word x]
sbb ax,0
not cx ;Set neg flag
p1_xok: mov [x+2],ax ;Save X
mov ax,[y+2] ;AX = y high word
test ax,ax ;Negative?
jge p1_yok
neg ax ;Negate Y
neg [word y]
sbb ax,0
not cx ;Flip neg flag
p1_yok: mov [y+2],ax ;Save Y
push cx ;Save neg flag
xor ax,ax ;Clear DX:AX, CX:BX
xor bx,bx ;DX:AX will contain
xor cx,cx ;the result, and
xor dx,dx ;CX:BX will be X.
mov si,48 ;SI = count
p1_loop: shl [word x],1 ;Shift in one bit of X
rcl [word x+2],1
adc bx,bx
adc cx,cx
add ax,ax ;Shift result left by 1
adc dx,dx
cmp cx,[y+2] ;Compare the partial X
jb p1_skip ;to Y, if X is bigger
ja p1_sub ;then Y is subtracted
cmp bx,[y] ;from the partial X.
jb p1_skip
p1_sub: sub bx,[y] ;Subtract Y from partial X
sbb cx,[y+2]
add ax,1 ;Add one bit to result
adc dx,0
p1_skip: dec si ;Loop back
jnz p1_loop
pop cx ;Restore neg flag
test cx,cx ;Check neg flag
jz p1_done
neg dx ;Negate result
neg ax
sbb dx,0
p1_done: pop si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP fixdiv
End
~~~C_FIXTOA
Ideal
Public fixtoa
Model Tiny
CodeSeg
P186
;****************** fixtoa() -- Convert fixed point number to string
;void fixtoa(int n, char *strp);
n equ bp+6
strp equ bp+4
Proc fixtoa
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov di,[strp] ;DI = string pointer
mov dx,[n+2] ;DX:AX = n
mov ax,[n]
test dx,dx ;Negative?
jge p1_noneg
mov [byte di],'-' ;Store minus sign
inc di
neg dx ;Make it positive
neg ax
sbb dx,0
p1_noneg: push dx ;Save DX
xor bx,bx ;Zero rem flag
add ax,ax ;Shift out high bit
adc bx,0 ;BX = rem flag
shr ax,1 ;Restore AX
mov cx,50000 ;AX = AX * 50000
mul cx
shr ax,15 ;AX = AX / 32768
shl dx,1
or ax,dx
pop dx ;Restore DX
push bx ax ;Save BX, AX
xchg dx,ax ;Integer part in AX
xor cx,cx ;Zero CX
mov si,10 ;SI = 10
p1_dloop: xor dx,dx ;Divide by 10
div si
mov bl,dl ;Remainder in BL
add bl,30h ;Convert to digit
push bx ;Push digit
inc cx
test ax,ax ;Loop back
jnz p1_dloop
p1_ploop: pop ax ;Pop digit
mov [di],al ;Store digit
inc di
loop p1_ploop ;Loop back
mov [byte di],'.' ;Store decimal point
inc di
pop ax bx ;Restore low data
xor dx,dx ;Zero DX
test bx,bx ;Check for high part
jz p1_nohigh
add ax,50000 ;Add in 50000
adc dx,0
p1_nohigh: mov si,10 ;SI = 10
mov cx,5 ;5 digits
jmp p1_skip1
p1_dloopb: xor dx,dx ;Zero DX
p1_skip1: div si ;Divide by 10
mov bl,dl ;Remainder in BL
add bl,30h ;Convert to digit
push bx ;Push digit
loop p1_dloopb ;Loop back
mov cx,5 ;5 digits
p1_ploopb: pop ax ;Pop digit
mov [di],al ;Store digit
inc di
loop p1_ploopb ;Loop back
mov [byte di],0 ;Add the null byte
p1_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 6 ;Return
EndP fixtoa
End
~~~C_ATOFIX
Ideal
Public atofix
Model Tiny
CodeSeg
P186
;****************** atofix() -- Convert string to fixed point number
;long atofix(char *strp);
strp equ bp+4
Proc atofix
push bp ;Set up stack frame
mov bp,sp
push bx cx si di bp ;Save registers
mov si,[strp] ;SI = string
xor ax,ax ;AX = 0
xor bh,bh ;BH = 0
mov cx,10 ;CX = 10
p1_ploop: mov bl,[si] ;Load char
inc si
cmp bl,' ' ;Loop while char is space
je p1_ploop ;(20h, or 09h thru 0Dh)
cmp bl,9
jna p1_go
cmp bl,13
jbe p1_ploop
p1_go: xor bp,bp ;BP = 0
cmp bl,'+' ;If char = '+', ignore
je p1_loop
cmp bl,'-' ;If char <> '-', keep it
jne p1_skip
inc bp ;Set negative flag
p1_loop: mov bl,[si] ;Load char
inc si
p1_skip: xor dx,dx ;Clear DX
cmp bl,'.' ;Decimal point, continue
je p1_cont
cmp bl,'9' ;Not a digit, finish
ja p1_finish
sub bl,'0'
jc p1_finish
mul cx ;Multiply by 10
add ax,bx ;Add in digit...
jmp p1_loop ;Loop back
p1_cont: push ax ;Save integer part
xor ax,ax ;Zero AX
mov di,1 ;DI = 1
p1_floop: mov bl,[si] ;Load char
inc si
cmp bl,'9' ;Not a digit, finish
ja p1_ffinish
sub bl,'0'
jc p1_ffinish
mul cx ;Multiply by 10
add ax,bx ;Add in digit...
adc dx,0
imul di,10 ;Multiply divisor by 10
jnc p1_floop ;Loop while < 5 digits
shr dx,1 ;5 digits, divide by 2
rcr ax,1 ;and set DI to 50000
mov di,50000 ;instead of 100000
p1_ffinish: mov dx,ax ;Multiply by 65536
xor ax,ax
div di ;Divide by 10^digits
mov dx,ax ;Fractional part in DX
pop ax ;Restore integer part
p1_finish: xchg dx,ax ;DX:AX = number
dec bp ;Positive, don't negate
jl p1_done
neg dx ;Negate the result
neg ax
sbb dx,0
p1_done: pop bp di si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP atofix
End
~~~C_BITS
Ideal
Public bitcnt,highbit
Model Tiny
P186
CodeSeg
;****************** bitcnt() -- Count set bits in integer
;int bitcnt(int x);
x equ bp+4
Proc bitcnt
push bp ;Set up stack frame
mov bp,sp
push bx cx ;Save registers
xor ax,ax ;Zero counter
mov bx,[x] ;BX = number
mov cx,16 ;16 bits
p1_loop: add bx,bx ;Shift out bit
adc ax,0 ;Add if carry
loop p1_loop ;Loop back
pop cx bx ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP bitcnt
;****************** highbit() -- Find high bit in integer
;int highbit(int x); returns -1 if it was zero
x equ bp+4
Proc highbit
push bp ;Set up stack frame
mov bp,sp
push bx ;Save registers
mov ax,15 ;Start with bit 15
mov bx,[x] ;BX = number
p2_loop: add bx,bx ;Shift out bit
jc p2_done ;Found a bit?
dec ax ;Loop back
jns p2_loop
p2_done: pop bx ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP highbit
End
~~~C_SQRT
Ideal
Public sqrt
Model Tiny
P186
CodeSeg
;****************** sqrt() -- Returns the square root of a
; long. Result is an integer.
;int sqrt(long num); 60-350 clocks (486)
num equ bp+4
Proc sqrt
push bp ;Set up stack frame
mov bp,sp
push cx dx ;Save registers
mov ax,[num] ;DX:AX = num
mov dx,[num+2]
mov cx,32 ;32 bits
p1_bloop: add ax,ax ;Find the highest set bit
adc dx,dx
jc p1_gotbit
loop p1_bloop
p1_gotbit: mov ax,1 ;CX = first guess 2^(log2(n)/2)
shr cx,1
shl ax,cl
mov cx,ax
p1_loop: mov ax,[num] ;DX:AX = num
mov dx,[num+2]
div cx ;AX = num/guess
add cx,ax ;CX = (guess+(num/guess))/2
shr cx,1
sub ax,cx ;If the difference is 1
cmp ax,1 ;or less, then done
ja p1_loop ;Loop back
mov ax,cx ;AX = result
pop dx cx ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP sqrt
End